<?php
// $Id: control_abstract.php 2554 2009-06-12 02:23:15Z jerry $


/**
 * 定义 QUI_Control_Abstract 类
 *
 * @link http://qeephp.com/
 * @copyright Copyright (c) 2006-2009 Qeeyuan Inc. {@link http://www.qeeyuan.com}
 * @license New BSD License {@link http://qeephp.com/license/}
 * @version $Id: control_abstract.php 2554 2009-06-12 02:23:15Z jerry $
 * @package webcontrols
 */

/**
 * QUI_Control_Abstract 是用户界面控件的基础类
 *
 * @author YuLei Liao <liaoyulei@qeeyuan.com>
 * @version $Id: control_abstract.php 2554 2009-06-12 02:23:15Z jerry $
 * @package webcontrols
 */
abstract class QUI_Control_Abstract {
	/**
	 * 运行时上下文
	 *
	 * @var QContext
	 */
	protected $_context;
	
	/**
	 * 渲染控件视图时要使用的视图变量
	 *
	 * @var array
	 */
	protected $_view = array ();
	
	/**
	 * 渲染控件视图时要使用的类
	 *
	 * @var string
	 */
	protected $_render_class = 'QView_Render_PHP_Parser';
	
	/**
	 * 视图渲染对象
	 *
	 * @var QView_Render_PHP
	 */
	protected $_render;
	
	/**
	 * 控件的 ID
	 *
	 * @var string
	 */
	protected $_id;
	
	/**
	 * 控件的属性
	 *
	 * @var array
	 */
	protected $_attrs;
	
	/**
	 * 构造函数
	 *
	 * @param string $id
	 * @param array $attrs
	 *
	 */
	function __construct($id, $attrs = array()) {
		$this->_context = QContext::instance ();
		$this->_id = $id;
		$this->_attrs = $attrs;
	}
	
	/**
	 * 返回或修改控件的 ID
	 *
	 * @param string $id 控件 ID
	 *
	 * @return string|QUI_Control_Abstract
	 */
	function id($id = null) {
		if (! is_null ( $id )) {
			$this->_id = $id;
			return $this;
		}
		
		if (! empty ( $this->_attrs ['qform_group_id'] )) {
			return "{$this->_attrs['qform_group_id']}_{$this->_id}";
		} else {
			return $this->_id;
		}
	}
	
	/**
	 * 返回或修改控件的 NAME
	 *
	 * @param string $name 控件 NAME
	 *
	 * @return string|QUI_Control_Abstract
	 */
	function name($name = null) {
		if (! is_null ( $name )) {
			$this->name = $name;
			return $this;
		}
		return $this->name ? $this->name : $this->id ();
	}
	
	function get($attr, $default = null) {
		return isset ( $this->_attrs [$attr] ) ? $this->_attrs [$attr] : $default;
	}
	
	function set($attr, $value = null) {
		if (is_array ( $attr )) {
			$this->_attrs = array_merge ( $this->_attrs, $attr );
		} else {
			$this->_attrs [$attr] = $value;
		}
		return $this;
	}
	
	/**
	 * 返回控件属性值
	 *
	 * @param string $attr
	 *
	 * @return mixed
	 */
	function __get($attr) {
		return isset ( $this->_attrs [$attr] ) ? $this->_attrs [$attr] : null;
	}
	
	/**
	 * 设置控件属性
	 *
	 * @param string $attr
	 * @param mixed $value
	 */
	function __set($attr, $value) {
		$this->_attrs [$attr] = $value;
	}
	
	function __isset($attr) {
		return isset ( $this->_attrs [$attr] );
	}
	
	function __unset($attr) {
		unset ( $this->_attrs [$attr] );
	}
	
	/**
	 * 返回或设置控件的所有属性
	 *
	 * @param array $attrs 控件属性
	 *
	 * @return array|QUI_Control_Abstract
	 */
	function attrs(array $attrs = null) {
		if (is_array ( $attrs )) {
			$this->_attrs = $attrs;
			return $this;
		}
		return $this->_attrs;
	}
	
	/**
	 * 显示一个控件
	 *
	 * @param QView_Render_PHP $render
	 *
	 * @return mixed
	 */
	function display($render = null) {
		if ($render instanceof QView_Render_PHP_Parser) {
			$this->_render = $render;
		}
		echo $this->render ();
	}
	
	function __toString() {
		return $this->render ();
	}
	
	/**
	 * 渲染一个控件，并返回渲染结果
	 *
	 * @return string
	 */
	abstract function render();
	
	/**
	 * 渲染指定的视图文件
	 *
	 * 渲染时，视图要使用的数据保存在控件的 $_view 属性中。
	 *
	 * @param string $filename
	 * @param array $more_vars
	 *
	 * @return string
	 */
	protected function _fetchView($filename, array $more_vars = null) {
		$this->_before_render ();
		$vars = $this->_view;
		$vars ['_ctx'] = $this->_context;
		$vars ['_CTL_ID'] = $this->id ();
		$vars ['_BASE_DIR'] = $this->_context->baseDir ();
		$vars ['_BASE_URI'] = $this->_context->baseUri ();
		$vars ['_REQUEST_URI'] = $this->_context->requestUri ();
		/*
        */
		// TODO! 全局变量应该放到 控件抽象类 _before_render() 中
		

		if (is_array ( $more_vars )) {
			$vars = array_merge ( $vars, $more_vars );
		}
		
		if (strpos ( $filename, 'view:' ) === 0) {
			$filename = Q::ini ( 'app_config/APP_DIR' ) . DS . 'view' . DS . ltrim ( substr ( $filename, 5 ), '/\\' );
		} elseif ($filename {0} != DS && strpos ( $filename, ':' ) === false) {
			$_class_name = strtolower ( get_class ( $this ) );
			$_sep = explode ( '_', $_class_name );
			array_pop ( $_sep );
			$filename = Q::ini ( 'app_config/APP_DIR' ) . DS . implode ( $_sep, DS ) . DS . ltrim ( $filename, '/\\' );
		}
		
		if (is_null ( $this->_render )) {
			$this->_render = new $this->_render_class ( dirname ( $filename ) );
		} else {
			// TODO! 假如共享视图解析器实例，需在此做必要处理
		}
		
		$this->_render->assign ( $vars );
		
		$extname = pathinfo ( $filename, PATHINFO_EXTENSION );
		$pextname = $this->_render->extname ();
		if (empty ( $extname ) || ($extname != $pextname && ! empty ( $pextname ))) {
			$filename .= '.' . (($pextname) ? $pextname : 'php');
		}
		
		return $this->_render->parse ( $filename );
	}
	
	/**
	 * 渲染之前调用
	 *
	 * 继承类可以覆盖此方法。
	 */
	protected function _before_render() {
	}
	
	protected function _extract($attr, $default = null) {
		$value = $this->get ( $attr, $default );
		unset ( $this->_attrs [$attr] );
		return $value;
	}
	
	/**
	 * 根据 ID 和 NAME 属性返回字符串
	 *
	 * @return string
	 */
	protected function _printIdAndName() {
		$out = ' id="' . htmlspecialchars ( $this->id () ) . '" ';
		if ($this->name) {
			$out .= 'name="' . htmlspecialchars ( $this->name ) . '" ';
		} else {
			$out .= 'name="' . htmlspecialchars ( $this->id () ) . '" ';
		}
		return $out;
	}
	
	protected function _printValue() {
		if (is_object ( $this->value ) && ! method_exists ( $this->value, '__toString' )) {
			return '';
		}
		return strlen ( $this->value ) ? 'value="' . htmlspecialchars ( $this->value ) . '" ' : '';
	}
	
	/**
	 * 根据 DISABLED 属性返回字符串
	 *
	 * @return string
	 */
	protected function _printDisabled() {
		return ($this->disabled) ? 'disabled="disabled" ' : '';
	}
	
	/**
	 * 根据 CHECKED 属性返回字符串
	 *
	 * @return string
	 */
	protected function _printChecked() {
		if ($this->checked_by_value) {
			return $this->value ? 'checked="checked" ' : '';
		} else {
			$checked = $this->checked;
			if (! $checked)
				return '';
			
			$value = $this->value;
			if ($value) {
				if ($checked == $value && strlen ( $checked ) == strlen ( $value ) && strlen ( $checked ) > 0) {
					return 'checked="checked" ';
				} else {
					return '';
				}
			} else {
				return 'checked="checked" ';
			}
		}
	}
	
	/**
	 * 构造控件的属性字符串
	 *
	 * @param array|string $exclude
	 *
	 * @return string
	 */
	protected function _printAttrs($exclude = 'id, name, value') {
		$exclude = Q::normalize ( $exclude );
		$exclude [] = 'qform_group_id';
		$exclude = array_flip ( $exclude );
		$out = '';
		foreach ( $this->_attrs as $attr => $value ) {
			if (isset ( $exclude [$attr] ))
				continue;
			$out .= $attr . '="' . htmlspecialchars ( $value ) . '" ';
		}
		return $out;
	}

}

